package org.linlinjava.litemall.wx.web;

import com.github.wxpay.sdk.WXPayUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.service.LitemallGoodsService;
import org.linlinjava.litemall.db.service.LitemallOrderService;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.linlinjava.litemall.wx.config.WXPayConstantConfig;
import org.linlinjava.litemall.wx.util.DateUtil;
import org.linlinjava.litemall.wx.util.HttpClientUtil;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

/**
 * 微信支付
 */
@RestController
@RequestMapping("/wx/order")
public class WXPayController {

    @Resource
    private LitemallOrderService orderService;

    /**
     * 通过返回io流获取指定的地址
     * @param is
     * @param key
     * @return
     */
    private String getEmelentValue(InputStream is, String key){
        SAXReader reader = new SAXReader();
        Document document = null;
        try {
            document = reader.read(is);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        Element root = document.getRootElement();
        List<Element> childElements = root.elements();
        for (Element child : childElements) {
            System.out.println(child.getName() + ":" + child.getStringValue());
            if(key.equals(child.getName())){
                return child.getStringValue();
            }
        }
        return null;
    }

    /**
     * 类型转换
     * @param matrix
     * @return
     */
    public static BufferedImage toBufferedImage(BitMatrix matrix){
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        for(int x = 0; x < width; x++){
            for(int y = 0; y < height; y++){
                image.setRGB(x, y, matrix.get(x, y) == true ? 0xff000000 : 0xFFFFFFFF);
            }
        }
        return image;
    }

    /**
     * 返回给微信
     * @param return_code
     * @param return_msg
     * @return
     */
    public static String setXML(String return_code, String return_msg) {
        return "<xml>" +
                "<return_code>" +
                "<![CDATA[" + return_code + "]]>" +
                "</return_code>" +
                "<return_msg>" +
                "<![CDATA[" + return_msg + "]]>" +
                "</return_msg>" +
                "</xml>";
    }

    /**
     * 生成二维码
     * 根据订单 id 要获得订单号
     * @return
     */
    @GetMapping("/getQrCode")
    public void getQrCode(HttpServletResponse response,@NotNull Integer orderId) throws Exception{
        Map<String,String> map = new HashMap<>();
        String xml = "";

        LitemallOrder order = orderService.findById(orderId);

        map.put("appid",WXPayConstantConfig.APPID);
        map.put("mch_id",WXPayConstantConfig.MCH_ID);                //商户号
        map.put("device_info",WXPayConstantConfig.DEVICE_INFO);     //设备号
        map.put("notify_url",WXPayConstantConfig.NOTIFY_URL);       //支付回调地址
        map.put("trade_type","NATIVE");  //交易类型
        map.put("out_trade_no",order.getOrderSn());  //商户订单号
        map.put("body",URLEncoder.encode(order.getOrderPrice()+"", "UTF-8"));       //应付金额
        map.put("total_fee","1");         //标价金额，单位是分，商品金额测试都为一分钱
        map.put("spbill_create_ip","127.0.0.1");                   //终端IP
        map.put("nonce_str",WXPayUtil.generateNonceStr());      //随机字符串
        map.put("sign",WXPayUtil.generateSignature(map, WXPayConstantConfig.KEY));      //签名

        xml = WXPayUtil.generateSignedXml(map,WXPayConstantConfig.KEY);
        System.out.println(xml);

        //得到一个输入流,发送xml的消息
        InputStream is = HttpClientUtil.sendXMLDataByPost(WXPayConstantConfig.REQUEST_URL,xml).getEntity().getContent();
        String code_url = getEmelentValue(is,"code_url");     //二维码地址

        MultiFormatWriter formatWriter = new MultiFormatWriter();
        Map hints = new HashMap();
        BitMatrix bitMatrix = null;
        //设置二维码像素大小
        bitMatrix = formatWriter.encode(code_url, BarcodeFormat.QR_CODE, 250, 250, hints);
        BufferedImage image = toBufferedImage(bitMatrix);
        //向页面输出png格式的二维码图片流，
        ImageIO.write(image, "png", response.getOutputStream());
    }


    private String status = "";

    /**
     * 异步请求处理notify_url
     */
    @PostMapping("/notifyUrl")
    public void notifyUrl(HttpServletRequest request,HttpServletResponse response) throws Exception{
        String s;
        //读取参数
        InputStream is;
        StringBuffer sb = new StringBuffer();

        //通过request返回一个xml的io流
        is = request.getInputStream();

        //一行一行读取
        BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        while((s = in.readLine()) != null){
            sb.append(s);
        }
        in.close();
        is.close();
        System.out.println("sb:" + sb.toString());

        Map<String, String> m = new HashMap<>();
        m = WXPayUtil.xmlToMap(sb.toString());

        //过滤空 设置TreeMap
        SortedMap<String, String> packageParam = new TreeMap<>();

        Iterator<String> it = m.keySet().iterator();
        while(it.hasNext()){
            String parameter = it.next();
            String parameterValue = m.get(parameter);

            String v = "";
            if(null != parameterValue){
                v = parameterValue.trim();
            }
            packageParam.put(parameter, v);

            //微信支付的密钥
            String key = WXPayConstantConfig.KEY;

            //验证签名
            if(WXPayUtil.isSignatureValid(packageParam, key)){
                //验证通过
                if("SUCCESS".equals((String)packageParam.get("result_code"))){
                    System.out.println("==========验证通过==========");
                    String noticeStr = setXML("SUCCESS", "OK");
                    String orderNo = (String) packageParam.get("out_trade_no");

                    if(orderService.updateByNo(202,0,orderNo)){
                        System.out.println("---------------修改成功----------------");
                    }

                    BufferedOutputStream out = new BufferedOutputStream(
                            response.getOutputStream());
                    out.write(noticeStr.getBytes());
                    out.flush();
                    out.close();
                    status = "success";
                }else{
                    System.out.println("==========验证失败==========");
                    status = "fail";
                }
            }
        }
    }

    /**
     * 返回是否支付成功
     * 0：未支付
     * 1：支付成功
     * 2：支付失败
     */
    @GetMapping("/paymentStatus")
    public Object paymentStatus(){
        if(status.equals("")){
            return 0;
        }
        return status.equals("success") ? 1 : -1;
    }

//    private int i = 0;
//
//    /**
//     * 获取支付状态
//     * @return
//     */
//    @PostMapping("/returnURL")
//    public Object returnURL(HttpServletResponse response) throws Exception{
//        i++;
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        if(i == 10){
//            status = 1;
//        }
//
//        System.out.println("i=" + i);
//        System.out.println("status=" + status);
//
//        response.setContentType("text/html;charset=UTF-8");
//        PrintWriter out = response.getWriter();
//        out.print(status);
//        out.flush();
//        out.close();
//        return null;
//    }

}
